﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

//using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Threading;
using System.Windows.Media.Imaging;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows;
using System.Media;
using Coding4Fun.Kinect.Wpf.Controls;
using System.Windows.Media;
using System.Text.RegularExpressions;
using Hugo.UIOptions;

namespace Hugo
{
    public class TileUIPage : UIPage
    {
        int selectedIndex;
        List<UIOption> pages;
        Dictionary<int, Rectangle> pageNameToSymbolMap;

        int currentpos = 0;

        bool showNavigationIcons = true;

        double positionYBaseline;

        Label currentSelectionLabel;

        const double OPACITY_UNSELECTED = 0.15;
        const double OPACITY_SELECTED = 1;

        const int labelFontSize = 110;

        const int PAGEMARK_SEPARATION = 300;

        static int counter = 0;

        const int PAGEMARK_WIDTH = 25;
        const int PAGEMARK_BUFFER = 15;

        int verticalBuffer = 10;

        Canvas IconCanvas;

        static int nextIconCanvasID = 0;

        public TileUIPage(String name, BitmapSource iconSource)
            : base(name, iconSource)
        {
            positionYBaseline = GlobalSettings.NavigationIconsBaseLineY - PAGEMARK_WIDTH - 40; // GlobalSettings.ScreenMiddleY + PAGEMARK_SEPARATION + VERTICAL_BUFFER;
            
            IconCanvas = new Canvas();
            IconCanvas.Name = name.Replace(" ","") + "_iconcanvas" + (nextIconCanvasID++);
            MainWindow.RegisterName(IconCanvas.Name, IconCanvas);
            this.PageCanvas.Children.Add(IconCanvas);

            if (this.showNavigationIcons)
            {
                Rectangle left = getSymbol(Util.loadBitmap(Properties.Resources.icon_left));
                //this.PageCanvas.Children.Add(left);

                Point p = getCenterOfPageMarkAtIndex(-1);
                Canvas.SetLeft(left, p.X);
                Canvas.SetTop(left, p.Y);

                Rectangle right = getSymbol(Util.loadBitmap(Properties.Resources.icon_right));
               // this.PageCanvas.Children.Add(right);

                p = getCenterOfPageMarkAtIndex(1);
                Canvas.SetLeft(right, p.X);
                Canvas.SetTop(right, p.Y);
            }

            pages = new List<UIOption>();
            pageNameToSymbolMap = new Dictionary<int, Rectangle>();

            
            currentSelectionLabel = new Label();


            //currentSelectionLabel.FontFamily = new FontFamily("Calibri");//new Uri("pack://Hugo:,,,/Resources/"), "./#Exo_Bold");

            currentSelectionLabel.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;

            currentSelectionLabel.Foreground = new SolidColorBrush(GlobalSettings.TextColor);
            currentSelectionLabel.FontSize = labelFontSize;
            PageCanvas.Children.Add(currentSelectionLabel);

            //Canvas.SetTop(currentSelectionLabel, this.positionYBaseline);
            
            // above stuff
            Canvas.SetTop(currentSelectionLabel, this.positionYBaseline - Util.getFontHeightFromSize(labelFontSize) - PAGEMARK_SEPARATION);

            List<UIOption> options = new List<UIOption>();

            //if (!name.Equals("Home"))
            //{
               
            //}
            options.Add(new UIInboxOption());
            options.Add(new TileUIPageShift(this, true));
            options.Add(new TileUISelectOption(this));
            options.Add(new TileUIPageShift(this, false));
            options.Add(new HomeUIOption());
            //options.Add(new BackUIOption());
            this.addNavigationUIOptions(options);

            timeTimer = new DispatcherTimer();
            timeTimer.Interval = TimeSpan.FromMilliseconds(0);
            timeTimer.Tick += new EventHandler(centerLabels);
            timeTimer.Start();
        }

        DispatcherTimer timeTimer;

        public void centerLabels(Object sender, EventArgs e)
        {
            // need to rerender to get updated width
            currentSelectionLabel.Dispatcher.Invoke(DispatcherPriority.Render, EmptyDelegate);
            Canvas.SetLeft(currentSelectionLabel, GlobalSettings.ScreenMiddleX - currentSelectionLabel.ActualWidth / 2);
            timeTimer.Stop();
        }

        private void setTransparent(Rectangle r)
        {
            r.Opacity = 0;
        }

        private void setOpaque(Rectangle r)
        {
            r.Opacity = 1;
        }

        public void addUIOption(UIOption page)
        {
            pages.Add(page);
            Regex rgx = new Regex("[^a-zA-Z0-9]");

            Point p2 = getCenterOfPageMarkAtIndex(pages.Count - 1);
            Rectangle el = Util.getSymbol(Util.loadBitmap(Properties.Resources.ellipse), PAGEMARK_WIDTH, PAGEMARK_WIDTH);
            IconCanvas.Children.Add(el);
            Canvas.SetLeft(el, p2.X);
            Canvas.SetTop(el, p2.Y);
            el.Name = "tileuipage" + (counter++) + rgx.Replace(page.Name, "") + pages.Count + "_el";
            this.MainWindow.RegisterName(el.Name, el);
            setTransparent(el);
            el.Opacity = OPACITY_UNSELECTED;

            pageNameToSymbolMap.Add(page.ID, el);

            currentpos = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width / 2 - (pages.Count * PAGEMARK_WIDTH + (pages.Count - 1) * PAGEMARK_BUFFER) / 2;
            Canvas.SetLeft(IconCanvas, currentpos);
        }

        public void clearPage()
        {
            pages.RemoveRange(0, pages.Count);

            int[] keys = new int[pageNameToSymbolMap.Keys.Count];
            int keyNo = 0;
            foreach (int key in pageNameToSymbolMap.Keys) {
                keys[keyNo++] = key;
            }

            foreach (int key in keys) {
                Rectangle r = pageNameToSymbolMap[key];
                IconCanvas.Children.Remove(r);
                pageNameToSymbolMap.Remove(key);
            }

            //pageNameToSymbolMap = new Dictionary<int, Rectangle>();
        }

        private Point getCenterOfPageMarkAtIndex(int index)
        {
            double x = index * (PAGEMARK_WIDTH + PAGEMARK_BUFFER); //(System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width / 2) - ICON_WIDTH_SELECTED / 2 + (ICON_WIDTH_SELECTED * index) + index * ICON_BUFFER;
            double y = this.positionYBaseline;
            return new Point(x, y);
        }

        private Rectangle getSelectedRectangle()
        {
            if (pageNameToSymbolMap.Count == 0) { return null; }
            return pageNameToSymbolMap[pages[selectedIndex].ID];
        }

        private UIOption getSelectedPage()
        {
            return pages[selectedIndex];
        }

        private Rectangle getRectangleAt(int index)
        {
            return pageNameToSymbolMap[pages[index].ID];
        }

        public void shiftRight()
        {
            int newIndex = this.selectedIndex + 1;
            if (newIndex == pages.Count) { newIndex = 0; }
            setSelectedIndex(newIndex);
        }

        private void speakPageSelectedAtIndex(int index)
        {
            Sounds.speakMessageAsync(pages[index].Name);
        }

        public void shiftLeft()
        {
            int newIndex = this.selectedIndex - 1;
            if (newIndex == -1) { newIndex = pages.Count - 1; }
            setSelectedIndex(newIndex);
        }

        private static Action EmptyDelegate = delegate() { };
        private Canvas currentPageContent;


        public void setSelectedIndex(int index)
        {
            if (getSelectedRectangle() == null) { return; }

            getSelectedRectangle().Opacity = OPACITY_UNSELECTED;

            int diff = this.selectedIndex - index;

            int oldIndex = this.selectedIndex;
            this.selectedIndex = index;

            currentSelectionLabel.Visibility = System.Windows.Visibility.Hidden;
            currentSelectionLabel.Content = pages[this.selectedIndex].Name;//.ToUpper();

            if (currentPageContent != null)
            {
                PageCanvas.Children.Remove(currentPageContent);
            }

            Canvas pageContent = pages[this.selectedIndex].getContent();
            if (pageContent != null)
            {
                currentPageContent = pageContent;
                PageCanvas.Children.Add(currentPageContent);

                double x = GlobalSettings.ScreenMiddleX - pageContent.ActualWidth / 2;
                double y = GlobalSettings.ScreenMiddleY - pageContent.ActualHeight / 2;

                Canvas.SetLeft(pageContent, 0);//x);
                Canvas.SetTop(pageContent, 0);//y);
            }

            // need to rerender to get updated width
            currentSelectionLabel.Dispatcher.Invoke(DispatcherPriority.Render, EmptyDelegate);
            Canvas.SetLeft(currentSelectionLabel, System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width / 2 - currentSelectionLabel.ActualWidth / 2);
            currentSelectionLabel.Visibility = System.Windows.Visibility.Visible;

            resizeOnCenter(getRectangleAt(oldIndex), ICON_WIDTH_SELECTED, ICON_HEIGHT_SELECTED);
            DoubleAnimation fadeOutSlightlyAnimation = AnimationFactory.getScaleAnimation(OPACITY_SELECTED, OPACITY_UNSELECTED);
            AnimationFactory.runStoryBoard(this.MainWindow,fadeOutSlightlyAnimation, getRectangleAt(oldIndex).Name, new PropertyPath(Canvas.OpacityProperty));

            resizeOnCenter(getSelectedRectangle(), ICON_WIDTH_SELECTED, ICON_HEIGHT_SELECTED);
            DoubleAnimation fadeInSlightlyAnimation = AnimationFactory.getScaleAnimation(OPACITY_UNSELECTED, OPACITY_SELECTED);
            AnimationFactory.runStoryBoard(this.MainWindow, fadeInSlightlyAnimation, getSelectedRectangle().Name, new PropertyPath(Canvas.OpacityProperty));

            getSelectedRectangle().Opacity = OPACITY_SELECTED;

            if (diff != 0)
            {
                if (GlobalSettings.isBlind)
                {
                    //Sounds.speakMessage
                    speakPageSelectedAtIndex(index);

                }
                else
                {
                    Sounds.playSound(Sounds.Sound.Navigate);
                }
            }
        }

        private void resizeOnCenter(Rectangle r, int newWidth, int newHeight)
        {
            DoubleAnimation widthAnimation = AnimationFactory.getScaleAnimation(r.ActualWidth, newWidth);
            DoubleAnimation heightAnimation = AnimationFactory.getScaleAnimation(r.ActualHeight, newHeight);

            double oldCenterX = Canvas.GetLeft(r) + r.ActualWidth / 2;
            double oldCenterY = Canvas.GetTop(r) + r.ActualHeight / 2;
            double newCenterX = Canvas.GetLeft(r) + newWidth / 2;
            double newCenterY = Canvas.GetTop(r) + newHeight / 2;

            DoubleAnimation xAnimation = AnimationFactory.getScaleAnimation(oldCenterX, newCenterX);
            DoubleAnimation yAnimation = AnimationFactory.getScaleAnimation(oldCenterY, newCenterY);

            Storyboard widthStoryBoard = new Storyboard();
            widthStoryBoard.Children.Add(widthAnimation);
            Storyboard.SetTargetName(widthAnimation, r.Name);
            Storyboard.SetTargetProperty(widthAnimation, new PropertyPath(Rectangle.WidthProperty));
            //widthStoryBoard.Begin(this.MainWindow);

            Storyboard heightStoryboard = new Storyboard();
            heightStoryboard.Children.Add(heightAnimation);
            Storyboard.SetTargetName(heightAnimation, r.Name);
            Storyboard.SetTargetProperty(heightAnimation, new PropertyPath(Rectangle.HeightProperty));
        }
       
        public List<UIOption> getUIPages()
        {
            return this.pages;
        }

        public override void setPage()
        {

            timeTimer = new DispatcherTimer();
            timeTimer.Interval = TimeSpan.FromMilliseconds(0);
            timeTimer.Tick += new EventHandler(centerLabels);
            timeTimer.Start();

            this.setSelectedIndex(this.selectedIndex);
            base.setPage();
        }

        int cursorSelectionPageName = -1;
        /*
        int cursorCountDown;
        const int HOLD_TIME = 5; //seconds
        
        Storyboard flashAnimationStoryboard;

        public void startFlashing(Rectangle r) {

            if (flashAnimationStoryboard != null)
            {
                flashAnimationStoryboard.Stop(this.MainWindow);
            }

            DoubleAnimation flashAnimation = AnimationFactory.getFastContinuousFadeAnimation(1,0.4);

            flashAnimationStoryboard = new Storyboard();
            flashAnimationStoryboard.Children.Add(flashAnimation);
            Storyboard.SetTargetName(flashAnimation, r.Name);
            Storyboard.SetTargetProperty(flashAnimation, new PropertyPath(Canvas.OpacityProperty));

            flashAnimationStoryboard.Begin(this.MainWindow, true);
        }
         */

        public override void setCursorPosition(Point p)
        {
            foreach (int pageName in pageNameToSymbolMap.Keys) {
                
                Rectangle r = pageNameToSymbolMap[pageName];
                double rX = Canvas.GetLeft(r) + currentpos;
                double rY = Canvas.GetTop(r) - verticalBuffer;
                double rX2 = rX + r.ActualWidth;
                double rY2 = rY + r.ActualHeight + verticalBuffer*2;

                if (rX < p.X && rY < p.Y && rX2 > p.X && rY2 > p.Y)
                {
                    if (cursorSelectionPageName != -1 || !cursorSelectionPageName.Equals(pageName))
                    {
                        setSelectedIndex(indexOfPage(pageName));
                        cursorSelectionPageName = pageName;

                    }
                }
            }

            base.setCursorPosition(p);
        }

        private int indexOfPage(int pageName)
        {
            for (int i = 0; i < pages.Count; i++)
            {
                if (pages[i].ID == pageName)
                {
                    return i;
                }
            }

            return -1;
        }

        public override void respondToKey(KeyEventArgs e)
        {
            if (e.Key == Key.Left)
            {
                shiftLeft();
            }
            else if (e.Key == Key.Right)
            {

                shiftRight();
            }
            else if (e.Key == Key.Enter)
            {
                //Sounds.playSound(Sounds.Sound.Accept);
                pushSelectedPage();
                
            }
            else if (e.Key == Key.Back)
            {

                //Sounds.playSound(Sounds.Sound.Accept);

                MainWindow.popPage();
            }
        }

        public void pushSelectedPage()
        {
            if (GlobalSettings.isBlind)
            {
                Sounds.speakMessage("Selecting");
            }

            UIOption selectedPage = getSelectedPage();
            selectedPage.wasSelected();

           
            
        }


        
    }
}
